package com.zenithmind.library.controller;

import com.zenithmind.common.result.Result;
import com.zenithmind.library.service.BookInventoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

/**
 * 图书库存管理控制器
 * 遵循单一职责原则：只负责图书库存相关的HTTP请求处理
 * 遵循开闭原则：通过接口依赖，支持功能扩展
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/library/book-inventory")
@RequiredArgsConstructor
@Tag(name = "图书库存管理", description = "图书库存的查询、借阅、归还、预约等功能")
public class BookInventoryController {

    private final BookInventoryService bookInventoryService;

    @GetMapping("/{bookId}/available-copies")
    @Operation(summary = "查询图书可借阅数量", description = "获取指定图书的可借阅副本数量")
    @PreAuthorize("hasAuthority('library:inventory:query')")
    public Result<Integer> getAvailableCopies(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId) {
        log.info("查询图书可借阅数量，图书ID：{}", bookId);
        Integer availableCopies = bookInventoryService.getAvailableCopies(bookId);
        return Result.success(availableCopies);
    }

    @GetMapping("/{bookId}/check-stock")
    @Operation(summary = "检查库存是否充足", description = "检查指定图书的库存是否满足需求数量")
    @PreAuthorize("hasAuthority('library:inventory:query')")
    public Result<Boolean> isStockSufficient(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId,
            @Parameter(description = "需求数量", required = true)
            @RequestParam Integer requestedQuantity) {
        log.info("检查库存是否充足，图书ID：{}，需求数量：{}", bookId, requestedQuantity);
        boolean sufficient = bookInventoryService.isStockSufficient(bookId, requestedQuantity);
        return Result.success(sufficient);
    }

    @PostMapping("/{bookId}/borrow")
    @Operation(summary = "借书操作", description = "执行图书借阅操作，原子性更新库存")
    @PreAuthorize("hasAuthority('library:inventory:borrow')")
    public Result<Void> borrowBook(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId) {
        log.info("执行借书操作，图书ID：{}", bookId);
        return bookInventoryService.borrowBook(bookId);
    }

    @PostMapping("/{bookId}/return")
    @Operation(summary = "还书操作", description = "执行图书归还操作，原子性更新库存")
    @PreAuthorize("hasAuthority('library:inventory:return')")
    public Result<Void> returnBook(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId) {
        log.info("执行还书操作，图书ID：{}", bookId);
        return bookInventoryService.returnBook(bookId);
    }

    @PostMapping("/{bookId}/reserve")
    @Operation(summary = "预约图书", description = "执行图书预约操作，原子性更新库存")
    @PreAuthorize("hasAuthority('library:inventory:reserve')")
    public Result<Void> reserveBook(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId) {
        log.info("执行预约操作，图书ID：{}", bookId);
        return bookInventoryService.reserveBook(bookId);
    }

    @DeleteMapping("/{bookId}/reserve")
    @Operation(summary = "取消预约", description = "取消图书预约，原子性更新库存")
    @PreAuthorize("hasAuthority('library:inventory:reserve')")
    public Result<Void> cancelReservation(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId) {
        log.info("取消预约操作，图书ID：{}", bookId);
        return bookInventoryService.cancelReservation(bookId);
    }

    @PutMapping("/{bookId}/stock")
    @Operation(summary = "更新图书库存", description = "更新图书的库存信息")
    @PreAuthorize("hasAuthority('library:inventory:update')")
    public Result<Void> updateBookStock(
            @Parameter(description = "图书ID", required = true)
            @PathVariable String bookId,
            @Parameter(description = "总库存", required = true)
            @RequestParam Integer totalCopies,
            @Parameter(description = "可借阅库存", required = true)
            @RequestParam Integer availableCopies) {
        log.info("更新图书库存，图书ID：{}，总库存：{}，可借阅库存：{}", bookId, totalCopies, availableCopies);
        return bookInventoryService.updateBookStock(bookId, totalCopies, availableCopies);
    }
}
